package fr.neticar.webremoteclient.server;

import java.awt.AWTKeyStroke;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;

import javax.servlet.http.HttpSession;
import javax.swing.KeyStroke;

import com.google.gwt.user.client.ui.KeyboardListener;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

import fr.neticar.webremoteclient.client.EventType;
import fr.neticar.webremoteclient.client.ImagePropertyBean;
import fr.neticar.webremoteclient.client.KeyboardEventBean;
import fr.neticar.webremoteclient.client.KeyboardUtils;
import fr.neticar.webremoteclient.client.MouseEventBean;
import fr.neticar.webremoteclient.client.WRCClientGateway;
import fr.neticar.webremoteclient.client.exception.WRCException;
import fr.neticar.webremoteclient.server.application.IRemoteClient;
import fr.neticar.webremoteclient.server.application.RemoteClientManager;

public class WRCClientGatewayImpl extends RemoteServiceServlet implements WRCClientGateway {

	public static final String REMOTE_CLIENT_SESSION_KEY = "remoteclient";

	public WRCClientGatewayImpl() {
	}

	public ImagePropertyBean getNextImage() {
		IRemoteClient client = getRemoteClient();
		ImagePropertyBean result = null;
		long timeout = System.currentTimeMillis() + 60000L;
		do {
			try {
				if (client.containsNewImage()) {
					result = client.getNextImageProperty();
					break;
				}
				if (System.currentTimeMillis() > timeout)
					break;
				Thread.sleep(100);
				continue;
			} catch (InterruptedException interruptedexception) {
			}
			break;
		} while (true);
		return result;
	}

	public void sendEvent(MouseEventBean event) {
		IRemoteClient client = getRemoteClient();
		if (client != null) {
			
			int id = -1;
			if (EventType.ON_MOUSE_DOWN.equals(event.getType()))
				id = MouseEvent.MOUSE_PRESSED;
			if (EventType.ON_MOUSE_UP.equals(event.getType()))
				id = MouseEvent.MOUSE_RELEASED;
			if (EventType.ON_MOUSE_MOVE.equals(event.getType()))
				id = MouseEvent.MOUSE_MOVED;
			MouseEvent evt = new MouseEvent(client.getEventSourceComponent(), id, 0, InputEvent.BUTTON1_MASK, event.getX(), event.getY(), 1, false);
			
			client.sendMouseEvent(evt, EventType.ON_MOUSE_MOVE.equals(event.getType()));
		}
	}

	public void sendEvent(KeyboardEventBean event) {
		IRemoteClient client = getRemoteClient();
		if (client != null) {
			
			int modifiers = 0;
			if (event.isAltModifier())
				modifiers = modifiers | KeyEvent.ALT_MASK;
			if (event.isShiftModifier())
				modifiers = modifiers | KeyEvent.SHIFT_MASK;
			if (event.isCtrlModifier())
				modifiers = modifiers | KeyEvent.CTRL_MASK;
			int id = 0;
			if (EventType.ON_KEY_DOWN.equals(event.getType())) {
				id = KeyEvent.KEY_PRESSED;
			}
			if (EventType.ON_KEY_UP.equals(event.getType())) {
				id = KeyEvent.KEY_RELEASED;
			}
			if (EventType.ON_KEY_TYPE.equals(event.getType())) {
				id = KeyEvent.KEY_TYPED;
			}
			if (!KeyboardUtils.isSpecialKey(event.getKeyChar())) {
				AWTKeyStroke keyStroke = KeyStroke.getAWTKeyStroke(new Character(event.getKeyChar()), modifiers);
				event.setKeyChar(keyStroke.getKeyChar());
				event.setKeyCode(keyStroke.getKeyCode());
			}
			if (event.getKeyCode() == KeyboardListener.KEY_ENTER) {
				event.setKeyCode(KeyEvent.VK_ENTER);
				event.setKeyChar((char) KeyEvent.VK_ENTER);
			}
			KeyEvent evt = new KeyEvent(client.getEventSourceComponent(), id, 0, modifiers, event.getKeyCode(), event.getKeyChar());
			System.out.println(event.getKeyChar()+"   "+ event.getKeyCode());
			client.sendKeyEvent(evt);
		}
	}

	private HttpSession getSession() {
		return this.getThreadLocalRequest().getSession();
	}
	
	private IRemoteClient getRemoteClient() {
		HttpSession session = getSession();
		return (IRemoteClient) session.getAttribute(REMOTE_CLIENT_SESSION_KEY);
	}

	public void startVNCClient(String host, String port, String password) throws WRCException {
		HttpSession session = getSession();
		IRemoteClient vncViewer = null;
		
		vncViewer = RemoteClientManager.getInstance().startNewRDPClient(host, port, password);
		
		session.setAttribute(REMOTE_CLIENT_SESSION_KEY, vncViewer);
	}

	public void stopVNCClient() {
		IRemoteClient client = getRemoteClient();
		if (client != null) {
			client.stop();
			HttpSession session = getSession();
			session.removeAttribute(REMOTE_CLIENT_SESSION_KEY);
		}
	}

	public int getScreenHeight() {
		IRemoteClient client = getRemoteClient();
		if (client != null) {
			return (int) client.getScreenHeight();
		}
		return 0;
	}

	public int getScreenWidth() {
		IRemoteClient client = getRemoteClient();
		if (client != null) {
			return (int) client.getScreenWidth();
		}
		return 0;
	}

}
